"""难度评估服务"""
from typing import Dict, Any, Optional
from app.db.question_bank import get_question_by_id, QUESTION_BANK
from app.core.database import RedisClient


class DifficultyService:
    """难度评估服务"""
    
    def __init__(self):
        try:
            self.redis = RedisClient.get_client()
            self.redis.ping()
        except Exception as e:
            print(f"警告: Redis连接失败，将使用内存存储: {e}")
            self.redis = None
            self._memory_storage = {}
    
    def get_difficulty_level(self, question_id: str) -> str:
        """
        获取题目难度级别
        
        Args:
            question_id: 题目ID
            
        Returns:
            难度级别: easy, medium, hard
        """
        question = get_question_by_id(question_id)
        if not question:
            return "medium"
        
        # 优先使用题目中的difficulty字段
        if question.get("difficulty"):
            return question["difficulty"]
        
        # 如果有difficulty_score，根据分数判断
        difficulty_score = question.get("difficulty_score")
        if difficulty_score is not None:
            if difficulty_score < 40:
                return "easy"
            elif difficulty_score < 70:
                return "medium"
            else:
                return "hard"
        
        # 基于题目特征评估难度
        return self._assess_difficulty_by_features(question)
    
    def _assess_difficulty_by_features(self, question: Dict[str, Any]) -> str:
        """
        基于题目特征评估难度
        
        评估因素：
        1. 选项数量（越多越难）
        2. 题目长度（越长可能越难）
        3. 知识点数量（越多越难）
        4. 是否为综合题（综合题更难）
        5. 解析长度（解析越长可能越难）
        """
        score = 50  # 基础分数
        
        # 选项数量
        options_count = len(question.get("options", []))
        if options_count > 4:
            score += 10
        
        # 题目长度
        content_length = len(question.get("content", ""))
        if content_length > 200:
            score += 10
        elif content_length < 50:
            score -= 5
        
        # 知识点数量
        knowledge_points = question.get("knowledge_points", [])
        if len(knowledge_points) > 3:
            score += 15
        elif len(knowledge_points) > 1:
            score += 5
        
        # 是否为综合题
        if question.get("category") == "综合" or question.get("subject") == "comprehensive":
            score += 20
        
        # 解析长度
        explanation_length = len(question.get("explanation", ""))
        if explanation_length > 300:
            score += 10
        
        # 转换为难度级别
        if score < 40:
            return "easy"
        elif score < 70:
            return "medium"
        else:
            return "hard"
    
    def calculate_difficulty_score(self, question_id: str) -> float:
        """
        计算题目难度评分（0-100）
        
        基于历史答题数据计算难度
        """
        # 从Redis获取该题目的历史答题数据
        correct_rate = self._get_historical_correct_rate(question_id)
        
        if correct_rate is None:
            # 如果没有历史数据，使用特征评估
            question = get_question_by_id(question_id)
            if not question:
                return 50.0
            
            # 基于特征计算分数
            base_score = 50.0
            options_count = len(question.get("options", []))
            knowledge_count = len(question.get("knowledge_points", []))
            is_comprehensive = question.get("category") == "综合"
            
            base_score += (options_count - 4) * 5
            base_score += knowledge_count * 10
            if is_comprehensive:
                base_score += 20
            
            return min(100, max(0, base_score))
        else:
            # 基于正确率计算难度（正确率越低，难度越高）
            difficulty_score = (1 - correct_rate) * 100
            return round(difficulty_score, 1)
    
    def _get_historical_correct_rate(self, question_id: str) -> Optional[float]:
        """获取题目的历史正确率"""
        if self.redis:
            try:
                # 从Redis获取该题目的答题统计
                stats_key = f"question_stats:{question_id}"
                stats = self.redis.hgetall(stats_key)
                if stats:
                    total = int(stats.get("total", 0) or 0)
                    correct = int(stats.get("correct", 0) or 0)
                    if total > 0:
                        return correct / total
            except Exception as e:
                print(f"获取历史正确率失败: {e}")
        
        # 从内存存储获取
        if hasattr(self, '_memory_storage'):
            stats = self._memory_storage.get(f"question_stats:{question_id}")
            if stats:
                total = stats.get("total", 0)
                correct = stats.get("correct", 0)
                if total > 0:
                    return correct / total
        
        return None
    
    def update_question_difficulty(self, question_id: str, is_correct: bool):
        """更新题目难度（基于答题结果）"""
        if self.redis:
            try:
                stats_key = f"question_stats:{question_id}"
                self.redis.hincrby(stats_key, "total", 1)
                if is_correct:
                    self.redis.hincrby(stats_key, "correct", 1)
                self.redis.expire(stats_key, 86400 * 365)  # 保存1年
            except Exception as e:
                print(f"更新题目难度失败: {e}")
        
        # 同时更新内存存储
        if not hasattr(self, '_memory_storage'):
            self._memory_storage = {}
        stats_key = f"question_stats:{question_id}"
        if stats_key not in self._memory_storage:
            self._memory_storage[stats_key] = {"total": 0, "correct": 0}
        self._memory_storage[stats_key]["total"] += 1
        if is_correct:
            self._memory_storage[stats_key]["correct"] += 1
        
        # 更新题目数据中的difficulty_score
        question = get_question_by_id(question_id)
        if question:
            new_score = self.calculate_difficulty_score(question_id)
            question["difficulty_score"] = new_score
            
            # 更新难度级别
            if new_score < 40:
                question["difficulty"] = "easy"
            elif new_score < 70:
                question["difficulty"] = "medium"
            else:
                question["difficulty"] = "hard"


# 单例实例
difficulty_service = DifficultyService()


